package jk.fox.transport.netty.server;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.AttributeKey;
import jk.fox.common.RpcDict;
import org.apache.log4j.Logger;

/**
 * @author cuichao
 * @Description: PingHandler
 * @Date: create in 2020/4/22 22:47
 * 服务端每隔一定空闲写时间ping
 */

public class PingHandler extends SimpleChannelInboundHandler<RpcDict.HeartBeat> {
    private static Logger logger = Logger.getLogger(PingHandler.class);

    private final int reset = 0;
    private int maxNoPingCount = 3;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcDict.HeartBeat msg) throws Exception {
        if(msg == RpcDict.HeartBeat.ping){
            logger.debug(ctx.channel().remoteAddress()+" has accept ping"+ctx.channel().localAddress());
            ctx.channel().writeAndFlush(RpcDict.HeartBeat.pong);
        }
        if(msg == RpcDict.HeartBeat.pong){
            ctx.channel().attr(AttributeKey.valueOf(RpcDict.PING_COUNTER)).set(reset);
        }

    }



    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {

        if(!(evt instanceof IdleStateEvent)){
            super.userEventTriggered(ctx,evt);
        }

        IdleStateEvent event = (IdleStateEvent)evt;
        if(event.state() == IdleState.READER_IDLE){
            int pingCount = (int)ctx.channel().attr(AttributeKey.valueOf(RpcDict.PING_COUNTER)).get();
            pingCount++;
            ctx.channel().attr(AttributeKey.valueOf(RpcDict.PING_COUNTER)).set(pingCount);
            if(pingCount > maxNoPingCount ){
                logger.debug(ctx.channel().remoteAddress()+"is time out, channel is close");
                ctx.disconnect();
                ctx.close();
            }
            ctx.writeAndFlush(RpcDict.HeartBeat.ping);
            logger.debug(ctx.channel().localAddress()+" has ping "+ctx.channel().remoteAddress());
        }

    }


}
